//******************************************************************************
/**
 *
 * @file	pair_poke.c
 * @brief	連れ歩きポケモン
 * @author	saito
 * @data	07.02.14
 *
 * モジュール名：PairPoke_  PairPokeEvAnm_
 *
 */
//******************************************************************************
#include "common.h"
#include "fieldsys.h"
#include "fieldobj.h"

#include "mapdefine.h"
#include "ev_pokemon.h"
#include "pair_poke.h"

#include "pair_poke_idx.h"

#include "poke_follow_def.h"

#include "zonedata.h"
#include "savedata/pair_poke_data.h"

#include "pair_poke_humor.h"

#include "field/pair_poke_info.h"

#define BALL_IN_EFF_WAIT	(20)
#define PC_BALL_IN_EFF_WAIT	(BALL_IN_EFF_WAIT)

//#define POKE_APP_DEBUG		//有効で、ボール格納してもポケが出現

typedef struct PC_BALL_IN_WORK_tag
{
	u8 Seq;
	u8 Counter;
	u8 Wait;
	u8 AnimeIdx;
	u8 Palette[16*2*2];
	BOOL IsLeft;
}PC_BALL_IN_WORK;

typedef struct BALL_IN_WORK_tag
{
	int Wait;
	u8 Palette[16*2*2];
}BALL_IN_WORK;

typedef struct PPOKE_PAL_FADE_WORK_tag
{
	s8 now_evy;
	u8 DivVal;
	u8 NowWait;
	u8 Wait;
	u16 PalSrc[16*2];
	u16 PalDst[16*2];
}PPOKE_PAL_FADE_WORK;

///static BOOL ChangeShaimeNormalFormEvt(GMEVENT_CONTROL * event);

//波乗り関連
static BOOL NaminoriEvt( GMEVENT_CONTROL *event );
static void MoveToPlayer(FIELD_OBJ_PTR player, FIELD_OBJ_PTR pair);

static int GetTexArcID(const int inObjCode);

static BOOL PCCounterBallIn(GMEVENT_CONTROL * event);
static u8 CheckPlayerPos(FIELDSYS_WORK * fsys, PC_BALL_IN_WORK *work);
static BOOL BallIn(GMEVENT_CONTROL * event);
static BOOL WhiteFlash(GMEVENT_CONTROL * event);

//==============================================================================
//	連れ歩きポケモン
//==============================================================================

//--------------------------------------------------------------
/**
 * 連れ歩きポケモンの再設定リクエスト
 *
 * @param	fsys			フィールドシステムポインタ
 *
 * @retval	none
 */
//--------------------------------------------------------------
void PairPoke_RequestReset(FIELDSYS_WORK *fsys)
{
	fsys->PairPokeWork.NeedReset = 1;
}

//--------------------------------------------------------------
/**
 * 自機の移動コマンドから連れ歩きポケモンのジャンプ移動コマンドを返す
 *
 * @param	inDir	方向
 * @param	code	アニメコマンド
 *
 * @retval	code	連れ歩きのアニメコマンド
 */
//--------------------------------------------------------------
int PairPoke_ChangeWalkToJumpCode(const int inDir, const int inCode)
{
	u8 i;
	int tbl_16f[] = {AC_WALK_U_16F,AC_WALK_D_16F,AC_WALK_L_16F,AC_WALK_R_16F};
	int tbl_8f[] = {AC_WALK_U_8F,AC_WALK_D_8F,AC_WALK_L_8F,AC_WALK_R_8F};
	int tbl_4f[] = {AC_WALK_U_4F,AC_WALK_D_4F,AC_WALK_L_4F,AC_WALK_R_4F};
	int tbl_2f[] = {AC_WALK_U_2F,AC_WALK_D_2F,AC_WALK_L_2F,AC_WALK_R_2F};

	for(i=0;i<DIR_4_MAX;i++){
		if (tbl_16f[i] == inCode){
			return tbl_8f[inDir];
		}
	}

	for(i=0;i<DIR_4_MAX;i++){
		if (tbl_8f[i] == inCode){
			return tbl_4f[inDir];
		}
	}

	for(i=0;i<DIR_4_MAX;i++){
		if (tbl_4f[i] == inCode){
			return tbl_2f[inDir];
		}
	}
	GF_ASSERT(0);
	return 0;
}

//--------------------------------------------------------------
/**
 * 段差ジャンプ描画オフセットを返す
 *
 * @param	fldobj	フィールドＯＢＪポインタ
 *
 * @retval	fx32	描画オフセット
 */
//--------------------------------------------------------------
fx32 PairPoke_GetJumpDrawOfs(FIELD_OBJ_PTR fldobj)
{
	int frame;
	u8 tbl_idx;
	fx32 jump_tbl[3][16] = {
		{
			0*FX32_ONE,8*FX32_ONE,12*FX32_ONE,8*FX32_ONE,
			0,0,0,0,
			0,0,0,0,
			0,0,0,0,
		},
		{
			0*FX32_ONE,6*FX32_ONE,8*FX32_ONE,10*FX32_ONE,
			12*FX32_ONE,10*FX32_ONE,8*FX32_ONE,	6*FX32_ONE,
			0,0,0,0,
			0,0,0,0,
		},
		{
			0*FX32_ONE,6*FX32_ONE,8*FX32_ONE,8*FX32_ONE,
			10*FX32_ONE,10*FX32_ONE,12*FX32_ONE,12*FX32_ONE,
			12*FX32_ONE,12*FX32_ONE,12*FX32_ONE,10*FX32_ONE,
			10*FX32_ONE,8*FX32_ONE,8*FX32_ONE, 6*FX32_ONE,
		},
	};

	if ( PairPoke_GetInfo_Fly(fldobj) ){
		return 0;
	}

	tbl_idx = FieldOBJ_GetMovePairJumpTblNo( fldobj );
	if (tbl_idx){
		tbl_idx--;
	}else{
		return 0;
	}

	frame = FieldOBJ_GetMovePairJumpFrame( fldobj );
	GF_ASSERT(frame < 16);
	return jump_tbl[tbl_idx][frame];
}

//--------------------------------------------------------------
/**
 * レア識別フラグ取得
 *
 * @param	fldobj	フィールドＯＢＪポインタ
 *
 * @retval	1：レア		0：レアじゃない
 */
//--------------------------------------------------------------
int PairPoke_IsRare(CONST_FIELD_OBJ_PTR fldobj)
{
	int flg;
	int param;
	int obj_id;
	//自分の連れ歩きではない場合は非レアを返す
	obj_id = FieldOBJ_OBJIDGet( fldobj );
	if ( obj_id != FLDOBJ_ID_POKE_PAIR
			&& obj_id != FLDOBJ_ID_SODATEYA01
			&& obj_id != FLDOBJ_ID_SODATEYA02){
	//if (FieldOBJ_OBJIDGet( fldobj ) != FLDOBJ_ID_POKE_PAIR){
		return 0;
	}
	param = FieldOBJ_ParamGet( fldobj, FLDOBJ_PARAM_2 );
	flg = (param)&0x1;
	return flg;
}

//--------------------------------------------------------------
/**
 * Viewセットオブジェクトかどうか？
 *
 * @param	fldobj	フィールドＯＢＪポインタ
 *
 * @retval	1：TRUE		0：FALSE
 */
//--------------------------------------------------------------
int PairPoke_IsSetViewObj(CONST_FIELD_OBJ_PTR fldobj)
{
	int code = FieldOBJ_OBJCodeGet( fldobj );

	if(code >= PAIR_POKEOBJ_S01 && code <= PAIR_POKEOBJ_L03){
		return TRUE;
	}
	return FALSE;
}

//--------------------------------------------------------------
/**
 * 連れ歩きポケモン情報取得 浮遊
 *
 * @param	fldobj	フィールドＯＢＪポインタ
 *
 * @retval	u8     浮遊している　1　していない　0
 */
//--------------------------------------------------------------
u8 PairPoke_GetInfo_Fly(CONST_FIELD_OBJ_PTR fldobj)
{
	u8 fly_flg;
	u16 param =	FieldOBJ_ParamGet( fldobj, FLDOBJ_PARAM_1 );
	//自分の連れ歩きではない場合は浮遊してないことにする
	if (FieldOBJ_OBJIDGet( fldobj ) != FLDOBJ_ID_POKE_PAIR){
		return 0;
	}
	fly_flg = (param & 0xff);	//8ビットマスク
	return ( (fly_flg >> 4) & 0xf);	//4ビットマスク
}

//--------------------------------------------------------------
/**
 * 連れ歩きポケモン情報取得 アニメ速度1/2か？
 *
 * @param	fldobj	フィールドＯＢＪポインタ
 *
 * @retval	u8     速度1/2　1　通常　0
 */
//--------------------------------------------------------------
u8 PairPoke_GetInfo_AnmSpd(CONST_FIELD_OBJ_PTR fldobj)
{
	u8 fly_flg;
	u16 param =	FieldOBJ_ParamGet( fldobj, FLDOBJ_PARAM_1 );
	//自分の連れ歩きではない場合は通常
	if (FieldOBJ_OBJIDGet( fldobj ) != FLDOBJ_ID_POKE_PAIR){
		return 0;
	}
	fly_flg = (param & 0xff);	//8ビットマスク
	return ( (fly_flg) & 0xf);	//4ビットマスク
}

//--------------------------------------------------------------
/**
 * 連れ歩きポケモン情報取得 大きいサイズか？
 *
 * @param	fldobj	フィールドＯＢＪポインタ
 *
 * @retval	u8     大きい　1　小さい　0
 */
//--------------------------------------------------------------
u8 PairPoke_GetInfo_BigSize(CONST_FIELD_OBJ_PTR fldobj)
{
	u8 big;
	u16 param =	FieldOBJ_ParamGet( fldobj, FLDOBJ_PARAM_1 );
	//自分の連れ歩きではない場合は小さいことにする
	if (FieldOBJ_OBJIDGet( fldobj ) != FLDOBJ_ID_POKE_PAIR){
		return 0;
	}

	big = (param >> 8 & 0xf);	//4ビットマスク

	return big;
}

#if 0
//--------------------------------------------------------------
/**
 * レア識別フラグセット
 *
 * @param	fldobj	フィールドＯＢＪポインタ
 *
 * @retval	none
 */
//--------------------------------------------------------------
void PairPoke_SetRare(FIELD_OBJ_PTR fldobj, BOOL inRare)
{
	int param;
	if (inRare){
		param = 1;
	}else{
		param = 0;
	}
	FieldOBJ_ParamSet( fldobj, param, FLDOBJ_PARAM_0 );
}

//--------------------------------------------------------------
/**
 * レア識別フラグ取得
 *
 * @param	fldobj	フィールドＯＢＪポインタ
 *
 * @retval	1：レア		0：レアじゃない
 */
//--------------------------------------------------------------
int PairPoke_IsRare(FIELD_OBJ_PTR fldobj)
{
	int param = FieldOBJ_ParamGet( fldobj, FLDOBJ_PARAM_0 );
	return param;
}
#endif
//--------------------------------------------------------------
/**
 * 現在いる座標の背後の座標を取得する
 *
 * @param	fldobj	フィールドＯＢＪポインタ
 * @param	outX	X座標格納先
 * @param	outZ	Z座標格納先
 *
 * @retval	none
 */
//--------------------------------------------------------------
void PairPoke_GetBackPos(CONST_FIELD_OBJ_PTR fldobj, int *outX, int *outZ)
{
	u8 dir = FieldOBJ_DirDispGet( fldobj );
	*outX = FieldOBJ_NowPosGX_Get( fldobj );
	*outZ = FieldOBJ_NowPosGZ_Get( fldobj );
	switch(dir){
	case DIR_UP:
		(*outZ)++;
		return;
	case DIR_DOWN:
		(*outZ)--;
		return;
	case DIR_LEFT:
		(*outX)++;
		return;
	case DIR_RIGHT:
		(*outX)--;
		return;
	}

	GF_ASSERT(0);
}

//--------------------------------------------------------------
/**
 * 旧座標の背後の座標を取得する
 *
 * @param	fldobj	フィールドＯＢＪポインタ
 * @param	outX	X座標格納先
 * @param	outZ	Z座標格納先
 *
 * @retval	none
 */
//--------------------------------------------------------------
void PairPoke_GetBackOldPos(CONST_FIELD_OBJ_PTR fldobj, int *outX, int *outZ)
{
	u8 dir = FieldOBJ_DirDispGet( fldobj );
	*outX = FieldOBJ_OldPosGX_Get( fldobj );
	*outZ = FieldOBJ_OldPosGZ_Get( fldobj );
	switch(dir){
	case DIR_UP:
		(*outZ)++;
		return;
	case DIR_DOWN:
		(*outZ)--;
		return;
	case DIR_LEFT:
		(*outX)++;
		return;
	case DIR_RIGHT:
		(*outX)--;
		return;
	}

	GF_ASSERT(0);
}

//--------------------------------------------------------------
/**
 * 現在いる座標の背後のアトリビュートを取得する
 *
 * @param	fldobj	フィールドＯＢＪポインタ
 * @param	inAttrDir	アトリビュート位置
 *
 * @retval	u16		アトリビュート
 */
//--------------------------------------------------------------
u16 PairPoke_GetDirAttr(CONST_FIELD_OBJ_PTR fldobj, POKE_ATTR_DIR inAttrDir)
{
	u16 attr;
	int x,z;
	FIELDSYS_WORK *fsys = FieldOBJ_FieldSysWorkGet( fldobj );

	x = FieldOBJ_NowPosGX_Get( fldobj );
	z = FieldOBJ_NowPosGZ_Get( fldobj );
	switch(inAttrDir){
	case POKE_ATTRDIR_UP:
		z--;
		break;
	case POKE_ATTRDIR_DOWN:
		z++;
		break;
	case POKE_ATTRDIR_LEFT:
		x--;
		break;
	case POKE_ATTRDIR_RIGHT:
		x++;
		break;
	case POKE_ATTRDIR_RD:
		x++;
		z++;
		break;
	case POKE_ATTRDIR_LD:
		x--;
		z++;
		break;
	}

	attr = GetAttributeLSB( fsys, x, z );

	return attr;
}

//--------------------------------------------------------------
/**
 * 自機のサイドに表示する
 *
 * @param	fldobj	自機フィールドＯＢＪポインタ
 * @param	fldobj_poke	連れ歩きフィールドＯＢＪポインタ
 * @param	inSideDir	自機の隣の位置
 * @param	inDir	ポケモンの向き
 *
 * @retval	none
 */
//--------------------------------------------------------------
void PairPoke_SetPlayerSide(FIELD_OBJ_PTR fldobj_player, FIELD_OBJ_PTR fldobj_poke, const u8 inSideDir, const u8 inDir)
{
	VecFx32 vec;

	FieldOBJ_VecPosGet( fldobj_player, &vec );
	switch(inSideDir){
	case DIR_UP:
		vec.z -= (FX32_ONE*16);
		break;
	case DIR_DOWN:
		vec.z += (FX32_ONE*16);
		break;
	case DIR_RIGHT:
		vec.x += (FX32_ONE*16);
		break;
	case DIR_LEFT:
		vec.x -= (FX32_ONE*16);
		break;
	}

	FieldOBJ_VecPosDirInit( fldobj_poke, &vec, inDir );
}

//--------------------------------------------------------------
/**
 * ポケモンがボールから出てくるアニメ
 *
 * @param	fldobj_poke	連れ歩きフィールドＯＢＪポインタ
 *
 * @retval	none
 */
//--------------------------------------------------------------
void PairPoke_Appear(FIELD_OBJ_PTR fldobj_poke)
{
	FE_MB_IO_Add( fldobj_poke, MB_OUT );
}

//--------------------------------------------------------------
/**
 * 自機フィールドＯＢＪと同じところに表示する
 *
 * @param	fsys			フィールドシステムポインタ
 * @param	inDir			方向
 *
 * @retval	none
 */
//--------------------------------------------------------------
void PairPoke_SetPlayerPos(FIELDSYS_WORK *fsys, u8 inDir)
{
	VecFx32 vec;
	FIELD_OBJ_PTR player,poke;

	if (!PairPoke_IsPairPoke(fsys)){
		return;
	}

	poke = PairPoke_GetFldObjPtr(fsys);
	player = Player_FieldOBJGet( fsys->player );

	FieldOBJ_VecPosGet( player, &vec );
	FieldOBJ_VecPosDirInit( poke, &vec, inDir );
}

//--------------------------------------------------------------
/**
 * 表示非表示チェック

 * @param	fsys			フィールドシステムポインタ
 *
 * @retval	BOOL	TRUE=非表示　FALSE=表示
 */
//--------------------------------------------------------------
BOOL PairPoke_IsVanish(FIELDSYS_WORK *fsys)
{
	FIELD_OBJ_PTR fldobj;
	fldobj = PairPoke_GetFldObjPtr(fsys);
	return FieldOBJ_StatusBitCheck_Vanish( fldobj );
}

//--------------------------------------------------------------
/**
 * ポケモン出現エフェクトの省略

 * @param	fsys			フィールドシステムポインタ
 *
 * @retval	none
 */
//--------------------------------------------------------------
void PairPoke_OmitAppearEffect(FIELDSYS_WORK *fsys)
{
	FIELD_OBJ_PTR fldobj;
	fldobj = PairPoke_GetFldObjPtr(fsys);
	FieldOBJ_OmitMovePairDispEff( fldobj );
}

//--------------------------------------------------------------
/**
 * レアカラーパレット変更
 *
 * @param	fos	フィールドＯＢＪシステムポインタ
 *
 * @retval	none
 */
//--------------------------------------------------------------
void PairPoke_ChgRarePal(FIELD_OBJ_SYS_PTR fos)
{
	int num,i;
	u8 *pltt_idx;
	//レアカラーに変更
	FIELD_OBJ_BLACT_CONT *cont = (FIELD_OBJ_BLACT_CONT *)FieldOBJSys_BlActContGet( fos );
	void *reso = LRes_IDResGet( cont->lres_anm, BLACT_ANMID_PAIR_POKE_RARE );
	u8* work = reso;

	// テーブル要素数取得
	// 最初の4byteはテーブル要素数
	num = *((u32*)work);
	work = work + sizeof(u32);		// 4byte移動

	// フレームデータテーブル先頭ポインタ設定
	work = work + (sizeof(u16) * num);	// テーブル分移動
	// テクスチャインデックスデータテーブル先頭ポインタ設定
	work = work + (sizeof(u8) * num);	// テーブル分移動

	// パレットインデックスデータテーブル先頭ポインタ設定
	pltt_idx = (u8*)work;
	//カラー書き換え
	for (i=0;i<num;i++){
		pltt_idx[i] = 1;
	}
}

//--------------------------------------------------------------
/**
 * カラーセット
 *
 * @param	inRare	レアカラーか？
 * @param	fldobj	フィールドＯＢＪポインタ
 * @param	act		アクターポインタ
 *
 * @retval	none
 */
//--------------------------------------------------------------
void PairPoke_SetColor(const BOOL inRare, FIELD_OBJ_PTR fldobj, BLACT_WORK_PTR act)
{
	int obj_id;
	BLACT_HEADER head;
	CONST_FIELD_OBJ_SYS_PTR fos =  FieldOBJ_FieldOBJSysGet( fldobj );
	FieldOBJ_BlActHeaderGetOBJCode( fos, FieldOBJ_OBJCodeGet( fldobj ), &head );

	//自分の連れ歩きではない場合は処理しない
	//if (FieldOBJ_OBJIDGet( fldobj ) != FLDOBJ_ID_POKE_PAIR){
	obj_id = FieldOBJ_OBJIDGet( fldobj );
	if ( obj_id != FLDOBJ_ID_POKE_PAIR
			&& obj_id != FLDOBJ_ID_SODATEYA01
			&& obj_id != FLDOBJ_ID_SODATEYA02){
		return;
	}

	PairPoke_LoadColToActHeader(inRare, fldobj, act, &head );
	BLACT_AnmSetChg( act, &head );
	{
		int no = FieldOBJ_BlActAnmOffsNo_DirWalkGet( FieldOBJ_DirDispGet( fldobj ) );
		BLACT_AnmOffsChg( act, no );
		BLACT_AnmFrameSetOffs( act, 0 );
	}
}

//--------------------------------------------------------------
/**
 * 通常カラー・レアカラーをアクターヘッダーにロード
 *
 * @param	inRare	レアカラーか？
 * @param	fldobj	フィールドＯＢＪポインタ
 * @param	act		アクターポインタ
 * @param	head	アクターヘッダー
 *
 * @retval	none
 */
//--------------------------------------------------------------
void PairPoke_LoadColToActHeader(const BOOL inRare,
									 FIELD_OBJ_PTR fldobj,
									 BLACT_WORK_PTR act,
									 BLACT_HEADER *head)
{
	CONST_FIELD_OBJ_SYS_PTR fos =  FieldOBJ_FieldOBJSysGet( fldobj );
	FIELD_OBJ_BLACT_CONT *cont = (FIELD_OBJ_BLACT_CONT *)FieldOBJSys_BlActContGet( fos );
	void *reso;
	int anm;
	if (inRare){
		anm = BLACT_ANMID_PAIR_POKE_RARE;
	}else{
		anm = BLACT_ANMID_PAIR_POKE;
	}
	reso = LRes_IDResGet( cont->lres_anm, anm );
	TEXANM_UnPackLoadFile( reso, &(head->texanm) );
}

typedef struct _PAIRPOKE_SETVIEW_WK{
	void *tex_buf;
	void* tex;
	u16 pal[16];
}PAIRPOKE_SETVIEW_WK;

static void vtcb_PairPokeSetViewResTrans( TCB_PTR tcb, void* p_work );

/**
 *	@brief	石像
 */
void PairPoke_SetView(const BOOL inRare, FIELD_OBJ_PTR fldobj, BLACT_WORK_PTR act)
{
	u16 monsno = 1;
	u32 siz;
	PAIRPOKE_SETVIEW_WK* wk;

	{
		VecFx32 vec;
		vec.x = FX32_CONST(0);
		vec.y = FX32_CONST(-8);
		vec.z = FX32_CONST(0);
//		FieldOBJ_VecDrawOffsSet( fldobj, &vec );
	}

	wk = sys_AllocMemoryLo(HEAPID_WORLD,sizeof(PAIRPOKE_SETVIEW_WK));
	MI_CpuClear8(wk,sizeof(HEAPID_WORLD));

	{
		int tex_id;
		ARCHANDLE *handle;
		NNSG3dResTex *tex;
		u16 *pData;
		u32 obj_code;

		obj_code = FieldOBJ_ParamGet(fldobj, FLDOBJ_PARAM_2);
		IWASAWA_PRINT("石像ObjCode SetView = %08x\n",obj_code);
		//下位1bitはレアフラグなので落とす
		tex_id = GetTexArcID( (obj_code>>1)&0xFFFF );

		handle = FieldOBJSys_ArcHandleGet(FieldOBJ_FieldOBJSysGet( fldobj ));
		wk->tex_buf = ArchiveDataLoadAllocByHandle( handle, tex_id, HEAPID_WORLD ); //アーカイブからロード
		tex = NNS_G3dGetTex((NNSG3dResFileHeader*) wk->tex_buf );
		pData = (u16*)GetPlttStartAdr(tex,0);
		wk->tex = GetTexStartAdr(tex, 0);
		siz = tex->plttInfo.sizePltt << 3;

		MI_CpuCopy16(pData,wk->pal,0x20);
	}
	PaletteGrayScale(wk->pal, 16);
	PaletteColorChange(wk->pal, 16, 256, 180, 0);

#if 1
	AddVramTransferManager(
		NNS_GFD_DST_3D_TEX_PLTT,		//転送セット
		NNS_GfdGetPlttKeyAddr( BLACT_GetPlttKey( act ) ),
		wk->pal,
//		NNS_GfdGetPlttKeySize(BLACT_GetPlttKey( act )));
		0x20);
	AddVramTransferManager(
			NNS_GFD_DST_3D_TEX_VRAM,						// テクスチャを転送
			NNS_GfdGetTexKeyAddr( BLACT_GetTexKey( act ) ),	// 転送先
			wk->tex,										// 転送データ
			NNS_GfdGetTexKeySize( BLACT_GetTexKey( act ) )	// 転送サイズ
			);

#endif
	// タスク登録
	VWaitTCB_Add( vtcb_PairPokeSetViewResTrans, wk, 0);
}

static void vtcb_PairPokeSetViewResTrans( TCB_PTR tcb, void* p_work )
{
	PAIRPOKE_SETVIEW_WK* wk = (PAIRPOKE_SETVIEW_WK*)p_work;

	if(GetVramTransferManagerAddNum()){
		return;
	}
	// メモリ解放
	TCB_Delete( tcb );

	sys_FreeMemoryEz(wk->tex_buf);
	sys_FreeMemoryEz( wk );
}

//--------------------------------------------------------------
/**
 * 連れ歩きポケモンにアニメーションコマンド発行が可能かチェック
 * @param	fsys	フィールドシステムポインタ
 * @retval	BOOL	TRUE=可能。FALSE=無理
 */
//--------------------------------------------------------------
BOOL PairPoke_CheckAcmdSet(FIELDSYS_WORK *fsys)
{
	FIELD_OBJ_PTR fldobj = PairPoke_GetFldObjPtr(fsys);
	return FieldOBJ_AcmdSetCheck(fldobj);
}

//--------------------------------------------------------------
/**
 * 連れ歩きポケモン遅延移動ワークに情報をセット
 * @param	inCode				アニメコマンドコード
 * @param	inGX				旧Ｘグリッド座標
 * @param	inGZ				旧Ｚグリッド座標
 * @param	pPairPokeWork		格納ワーク
 *
 * @retval	none
 */
//--------------------------------------------------------------
void PairPoke_SetLateMoveInfo(	const int inCode, const int inGX, const int inGZ,
									PAIR_POKE_INFO_WORK *pPairPokeWork	)
{
	pPairPokeWork->AnimeCommand = inCode;
	//自機座標保存
	pPairPokeWork->GridX = inGX;
	pPairPokeWork->GridZ = inGZ;
	if (pPairPokeWork->Code == AC_DONE){
		pPairPokeWork->Code = AC_READY;
//		OS_Printf("code_ready\n");
	}else if (pPairPokeWork->Code == AC_NONE){
		pPairPokeWork->Code = AC_START;
//		OS_Printf("code_start\n");
	}
}

//--------------------------------------------------------------
/**
 * 連れ歩きポケモン再設定
 * @param	fsys		フィールドシステムポインタ
 * @retval	none
 */
//--------------------------------------------------------------
void PairPoke_Reset(FIELDSYS_WORK *fsys)
{
	if (fsys->PairPokeWork.NeedReset){
		if (fsys->PairPokeWork.Follow == 0){
			PairPoke_Init( fsys->fldobjsys,
					Player_NowGPosXGet(fsys->player),
					Player_NowGPosZGet(fsys->player),
					Player_DirGet(fsys->player),
					fsys->location->zone_id);
			{
				//連れ歩いていない状態からのポケセット時に、レアカラーが反映されないので、ここで初回描画フラグを落としてレアカラーセットしてもらう
				FIELD_OBJ_PTR fldobj = fsys->PairPokeWork.FldObj;
				if (fsys->PairPokeWork.Follow == 1){
					FieldOBJ_SetFirstDrawFlgOFF( fldobj );
					///FieldOBJ_SetPokeColorPlt( PairPoke_IsRare(fldobj), fldobj );
				}
			}
		}else{
			int monsno;
			//連れ歩きポケモンのモンスターナンバーを取得
			monsno = PairPoke_GetMonsNo(fsys->PairPokeWork.FldObj);
			//連れ歩けるかをチェック
			if ( !PairPoke_CheckFollowable(monsno, fsys->location->zone_id) ){ //連れ歩けない
				//連れ歩きポケモンフィールドＯＢＪを削除
				FieldOBJ_Delete( fsys->PairPokeWork.FldObj );
				fsys->PairPokeWork.Follow = 0;
				OS_Printf("PairPoke Delete\n");
			}
		}
	}
	fsys->PairPokeWork.NeedReset = 0;
}

//--------------------------------------------------------------
/**
 * 連れ歩きポケモン高さ再設定
 * @param	fsys			フィールドシステムポインタ
 * @param	inY			高さ
 */
//--------------------------------------------------------------
void PairPoke_SetVecPosY(FIELDSYS_WORK *fsys, const fx32 inY )
{
	if ( PairPoke_IsPairPoke(fsys) ){
		VecFx32 vec;
		FIELD_OBJ_PTR pair = PairPoke_GetFldObjPtr(fsys);
		//連れ歩きポケモン座標取得
		FieldOBJ_VecPosGet( pair, &vec );
		//連れ歩きポケモン座標更新
		vec.y = inY;
		FieldOBJ_VecPosSet( pair, &vec );
	}
}

////==============================================================================================

//--------------------------------------------------------------
/**
 * 連れ歩きポケモンアニメ終了待ちイベント
 * イベントコールでつなぐなどして使用する
 *
 * @param	event	イベントポインタ
 *
 * @retval	BOOL	TRUE:イベント終了	FALSE:イベント継続
 */
//--------------------------------------------------------------
BOOL PairPokeEvAnm_WaitAnmEvent(GMEVENT_CONTROL * event)
{
	FIELDSYS_WORK * fsys = FieldEvent_GetFieldSysWork(event);
	int *seq = FieldEvent_GetSeqWork(event);
	FIELD_OBJ_PTR fldobj;

	if (!PairPoke_IsPairPoke(fsys)){
		return TRUE;
	}

	fldobj = fsys->PairPokeWork.FldObj;

	switch(*seq){
	case 0:	//ポーズを解除
		if ( FieldOBJ_MovePauseCheck( fldobj ) ){
			FieldOBJ_MovePauseClear( fldobj );
			(*seq) = 1;
		}else{
			//そもそもポーズしてない
			(*seq) = 2;
		}
		break;
	case 1:		//ポーズを解除した場合のアニメ監視シーケンス
		//ポケモンの移動アニメを監視
		if ( FieldOBJ_AcmdEndCheck(fldobj) && FieldOBJ_AcmdSetCheck(fldobj) ){
			//ポーズ状態に戻す
			FieldOBJ_MovePause( fldobj );
			return TRUE;
		}
		break;
	case 2:	//ポーズを解除しなかった場合のアニメ監視シーケンス
		//ポケモンの移動アニメを監視
		if ( FieldOBJ_AcmdEndCheck(fldobj) && FieldOBJ_AcmdSetCheck(fldobj) ){
			return TRUE;
		}
	}
	return FALSE;
}

//--------------------------------------------------------------
/**
 * ポケモン回復時の連れ歩きポケモンアニメのイベントを作成
 *
 * @param	fsys	フィールドシステムポインタ
 *
 * @retval	none
 */
//--------------------------------------------------------------
void PairPokeEvAnm_PCCounterBallIn(FIELDSYS_WORK * fsys)
{
	PC_BALL_IN_WORK *work;
	//メモリ確保
	{
		work = sys_AllocMemoryLo(HEAPID_WORLD, sizeof(PC_BALL_IN_WORK));
		work->Seq = 0;
		work->Counter = 0;
		work->Wait = 0;
		work->AnimeIdx = 0;
	}

	//イベントコール
	FieldEvent_Call(fsys->event, PCCounterBallIn, work);
///	FieldEvent_Set(fsys, PCCounterBallIn, work);
}

//--------------------------------------------------------------
/**
 * ポケセンカウンターへ連れ歩きポケモンが移動して、ボールに入る
 *
 * @param	event	イベントポインタ
 *
 * @retval	BOOL	TRUE:イベント終了	FALSE:イベント継続
 */
//--------------------------------------------------------------
static BOOL PCCounterBallIn(GMEVENT_CONTROL * event)
{
	FIELDSYS_WORK * fsys = FieldEvent_GetFieldSysWork(event);
	PC_BALL_IN_WORK * work = FieldEvent_GetSpecialWork(event);

	switch (work->Seq) {
	case 0:
		//ポケモン連れ歩いていない
		if (!PairPoke_IsPairPoke(fsys)){	//連れ歩いていないなら演出カット
			sys_FreeMemoryEz(work);
			return TRUE;
		}
		//ポケモン消えてないか？
		if (PairPoke_IsVanish(fsys)){	//消えてたら、演出カット
			sys_FreeMemoryEz(work);
			return TRUE;
		}

		//連れ歩きポケモンポーズ解除
		FieldOBJ_MovePauseClear( PairPoke_GetFldObjPtr(fsys) );
		work->Seq++;
	case 1:
		//ポケモンの移動アニメを終わらせる
		if ( FieldOBJ_AcmdEndCheck( PairPoke_GetFldObjPtr(fsys) ) ){
			//ポケモンと自機の相対位置から、アニメ分岐
			work->Seq = CheckPlayerPos(fsys, work);
		}
		break;
	case 2:
		//主人公の下
		{
			int anime_code[2] = {AC_WALK_L_8F,AC_WALK_U_8F};
			FIELD_OBJ_PTR ptr = PairPoke_GetFldObjPtr(fsys);
			if ( FieldOBJ_AcmdEndCheck(ptr) ){
				FieldOBJ_AcmdSet(ptr, anime_code[work->AnimeIdx++]);	//アニメセット
				if (work->AnimeIdx >= 2){
					work->Seq++;
				}
			}
		}
		break;
	case 3:
		{
			FIELD_OBJ_PTR ptr = PairPoke_GetFldObjPtr(fsys);
			if ( FieldOBJ_AcmdEndCheck( ptr ) ){
				//上を向く
				FieldOBJ_AcmdSet(ptr, AC_DIR_U);
				work->Seq++;
			}
		}
		break;
	case 4:
		{
			VecFx32 vec;
			fx32 add_x;
			s8 z_tbl[8] = {4,4,4,2,2,2,0,0};	//合計：上に18
//			s8 x_tbl[8] = {1,1,1,2,2,3,3,3};
			s8 y_tbl[8] = {1,2,2,3,3,2,2,0};
			//ポケモンの上方向に主人公がいる場合
			//ポケモンのＺ座標をマイナスする。Ｙ座標を上げる
			FIELD_OBJ_PTR  ptr = PairPoke_GetFldObjPtr(fsys);

			add_x = (FX32_ONE*2);
			if (!work->IsLeft){
				add_x *= -1;
			}
			FieldOBJ_VecPosGet( ptr, &vec );
			vec.z -= (FX32_ONE*z_tbl[work->Counter]);
			vec.x += add_x;
			vec.y += (FX32_ONE*y_tbl[work->Counter]);
			FieldOBJ_VecPosSet( ptr, &vec );

			work->Counter++;
			if (work->Counter >= 8){
				work->Seq++;
			}
		}
		break;
	case 5:
		{
			FIELD_OBJ_PTR  ptr = PairPoke_GetFldObjPtr(fsys);
			//ボールに格納
			FE_MB_IO_Add(ptr, MB_IN_PC);
			work->Seq++;
		}
		break;
	case 6:
		OS_Printf("wait=%d\n",work->Wait);
		if (++work->Wait >= PC_BALL_IN_EFF_WAIT){
			//ポケモンを主人公の位置へ
			PairPoke_SetPlayerPos(fsys, DIR_UP);
			//ポケモンのサイズ戻す
			{
				BLACT_WORK_PTR	act;
				VecFx32 scale = {FX32_ONE,FX32_ONE,FX32_ONE};
				//連れ歩きポケモンアクター取得
				act = FldOBJ_GetPairPokeAct(fsys->fldobjsys);
				//連れ歩きポケモンを元のサイズにする
				BLACT_ScaleSet(act, &scale);
				//一歩移動で演出あり
				PairPoke_SetAppAnmPrm(fsys->PairPokeWork.FldObj, TRUE);
			}
			work->Seq++;
		}
		break;
	case 7:
		sys_FreeMemoryEz(work);
		return TRUE;
		break;
	}

	return FALSE;
}

//--------------------------------------------------------------
/**
 * 自機と連れ歩きポケモンの相対位置から次のイベントシーケンスを返す
 *
 * @param	fsys	フィールドシステムポインタ
 * @param	work	イベントワーク
 *
 * @retval	u8		シーケンス番号
 */
//--------------------------------------------------------------
static u8 CheckPlayerPos(FIELDSYS_WORK * fsys, PC_BALL_IN_WORK *work)
{
	int ply_x,ply_z;
	int poke_x,poke_z;
	//自機の位置取得
	ply_x = FieldOBJ_NowPosGX_Get( Player_FieldOBJGet( fsys->player ) );
	ply_z = FieldOBJ_NowPosGZ_Get( Player_FieldOBJGet( fsys->player ) );
	//ポケモンの位置取得
	poke_x = FieldOBJ_NowPosGX_Get( PairPoke_GetFldObjPtr(fsys) );
	poke_z = FieldOBJ_NowPosGZ_Get( PairPoke_GetFldObjPtr(fsys) );
	//ポケモンが自機の下
	if ( (poke_x == ply_x)&&(poke_z == ply_z+1) ){
		work->IsLeft = TRUE;
		return 2;
	}
	else if ( (poke_x == ply_x+1)&&(poke_z == ply_z) ){
		//ポケモンが自機の右
		work->IsLeft = FALSE;
		return 3;
	}else if ((poke_x+1 == ply_x)&&(poke_z == ply_z)){
		//ポケモンが自機の左
		work->IsLeft = TRUE;
		return 3;
	}else{
		GF_ASSERT(0);
	}
	return 2;
}

//--------------------------------------------------------------
/**
 * 連れ歩きポケモンをボールに格納するイベントを作成
 *
 * @param	fsys	フィールドシステムポインタ
 *
 * @retval	BOOL		TRUE:イベント作成	FALSE:イベント未作成
 */
//--------------------------------------------------------------
BOOL PairPokeEvAnm_BallIn(FIELDSYS_WORK * fsys)
{
	BALL_IN_WORK *work;

	//ポケモン連れ歩いていない
	if (!PairPoke_IsPairPoke(fsys)){	//連れ歩いていないなら演出カット
		return FALSE;
	}
	//ポケモン消えてないか？
	if (PairPoke_IsVanish(fsys)){	//消えてたら、演出カット。ただし、格納状態にはする
		//連れ歩きポケモンを格納状態にする
		PairPoke_SetBallInState(fsys);
		//ポケモンを主人公の位置へ
		PairPoke_SetPlayerPos(fsys, DIR_UP);
		return FALSE;
	}

	//メモリ確保
	{
		work = sys_AllocMemoryLo(HEAPID_WORLD, sizeof(BALL_IN_WORK));
		work->Wait = 0;
	}

	//イベントコール
	FieldEvent_Call(fsys->event, BallIn, work);
///	FieldEvent_Set(fsys, BallIn, work);
	return TRUE;
}

//--------------------------------------------------------------
/**
 * 連れ歩きポケモンが移動して、ボールに入る
 *
 * @param	event	イベントポインタ
 *
 * @retval	BOOL	TRUE:イベント終了	FALSE:イベント継続
 */
//--------------------------------------------------------------
static BOOL BallIn(GMEVENT_CONTROL * event)
{
	FIELDSYS_WORK * fsys = FieldEvent_GetFieldSysWork(event);
	BALL_IN_WORK * work = FieldEvent_GetSpecialWork(event);
	int *seq = FieldEvent_GetSeqWork(event);

	switch (*seq) {
	case 0:
		//連れ歩きポケモンポーズ解除
		FieldOBJ_MovePauseClear( PairPoke_GetFldObjPtr(fsys) );
		(*seq)++;
	case 1:
		//ポケモンの移動アニメを終わらせる
		if ( FieldOBJ_AcmdEndCheck( PairPoke_GetFldObjPtr(fsys) ) ){
			(*seq)++;
		}
		break;
	case 2:
		{
			FIELD_OBJ_PTR  ptr = PairPoke_GetFldObjPtr(fsys);
			//パレット保存
			{
				int tex_id;
				u8 *start;
				ARCHANDLE *handle;
				void *arc_data;
				NNSG3dResTex *tex;

				tex_id = GetTexArcID( FieldOBJ_OBJCodeGet( ptr ) );	//テクスチャアーカイブIDを取得
				handle = FieldOBJSys_ArcHandleGet( fsys->fldobjsys );
				arc_data = ArchiveDataLoadAllocByHandle( handle, tex_id, HEAPID_WORLD ); //アーカイブからロード
				tex = NNS_G3dGetTex((NNSG3dResFileHeader*) arc_data );
				//パレットロウデータ取得
				start = (u8*)tex + tex->plttInfo.ofsPlttData;
				//パレットコピー
				MI_CpuCopy16( start, work->Palette, 16*2*2 );	//16色パレット2本分

				sys_FreeMemoryEz(arc_data);
			}
			//ボールに格納
			FE_MB_IO_Add(ptr, MB_IN);
			(*seq)++;
		}
		break;
	case 3:
		if (++work->Wait >= BALL_IN_EFF_WAIT){
			//ポケモンを主人公の位置へ
			PairPoke_SetPlayerPos(fsys, DIR_UP);
			//ポケモンのサイズ戻す
			{
				BLACT_WORK_PTR	act;
				VecFx32 scale = {FX32_ONE,FX32_ONE,FX32_ONE};
				//連れ歩きポケモンアクター取得
				act = FldOBJ_GetPairPokeAct(fsys->fldobjsys);
				//連れ歩きポケモンを元のサイズにする
				BLACT_ScaleSet(act, &scale);
				//パレット戻す
				AddVramTransferManager(
					NNS_GFD_DST_3D_TEX_PLTT,		//転送セット
					NNS_GfdGetPlttKeyAddr( BLACT_GetPlttKey( act ) ),
					work->Palette,
					NNS_GfdGetPlttKeySize(BLACT_GetPlttKey( act )));
				//連れ歩きポケモンを格納状態にする
				PairPoke_SetBallInState(fsys);
				//段差ジャンプ直前に格納されたかもしれないので、段差状態をクリア
				PairPoke_SetJumpDirPrm( PairPoke_GetFldObjPtr(fsys), 0 );
				//↑上向き段差はないのでクリア値として0==DIR_UPを入れとく
#ifdef POKE_APP_DEBUG
				PairPoke_SetVanishTalkFlg(PairPoke_GetFldObjPtr(fsys), FALSE);
				//↑ポケ表示自転車乗ってるときとかのポケの位置確認デバッグ用
#endif
			}
			(*seq)++;
		}
		break;
	case 4:
		sys_FreeMemoryEz(work);
		return TRUE;
		break;
	}

	return FALSE;
}

//--------------------------------------------------------------
/**
 * 連れ歩きポケモン波乗りイベントコール
 *
 * @param	event	イベントポインタ
 *
 * @retval	none
 */
//--------------------------------------------------------------

void PairPoke_CallNaminoriEvt( GMEVENT_CONTROL *event )
{
	int *wait;
	wait = sys_AllocMemoryLo(HEAPID_WORLD, sizeof(int));
	*wait = 0;
	FieldEvent_Call( event, NaminoriEvt, wait );
}

//--------------------------------------------------------------
/**
 * 波乗り開始時の連れ歩きの動作イベント
 *
 * @param	event	イベントポインタ
 *
 * @retval	BOOL	TRUE:イベント終了	FALSE:イベント継続
 */
//--------------------------------------------------------------
static BOOL NaminoriEvt( GMEVENT_CONTROL *event )
{
	int *seq;
	int *wait;
	FIELDSYS_WORK * fsys = FieldEvent_GetFieldSysWork(event);
	wait = FieldEvent_GetSpecialWork( event );
	seq = FieldEvent_GetSeqWork(event);
	switch( *seq ){
	case 0:
		//グリッドセンターへ移動
		FieldObj_SetPairPokeGridCenter( fsys->PairPokeWork.FldObj );
		FieldOBJ_DrawProcCall( fsys->PairPokeWork.FldObj );
		(*seq)++;
		break;
	case 1:
		//自機のいる場所に移動
		if( FieldOBJ_AcmdSetCheck(fsys->PairPokeWork.FldObj) == TRUE ){
			MoveToPlayer(Player_FieldOBJGet( fsys->player ), fsys->PairPokeWork.FldObj);
			(*seq)++;
		}
		break;
	case 2:
		//向き変更
		if( FieldOBJ_AcmdSetCheck(fsys->PairPokeWork.FldObj) == TRUE ){
			FieldOBJ_DirDispCheckSet( fsys->PairPokeWork.FldObj,
									  FieldOBJ_DirDispGet(Player_FieldOBJGet( fsys->player )) );
			(*seq)++;
		}
		break;
	case 3:
		//ウェイト
		(*wait)++;
		if (*wait > 10){
			(*seq)++;
		}
		break;
	case 4:
		//アニメ待ち
		if(FieldOBJ_AcmdSetCheck(fsys->PairPokeWork.FldObj) == TRUE){
			int code;
			//バニッシュしてる場合もあるのでここで表示
			PairPoke_SetVanishTalkFlg( fsys->PairPokeWork.FldObj, 0 );
			//水面にジャンプ
			code = FieldOBJ_AcmdCodeDirChange(
					FieldOBJ_DirDispGet(Player_FieldOBJGet( fsys->player )), AC_JUMP_U_1G_8F );
			FieldOBJ_AcmdSet( fsys->PairPokeWork.FldObj, code );
			(*seq)++;
		}
		break;
	case 5:
		//アニメ待ち
		if(FieldOBJ_AcmdSetCheck(fsys->PairPokeWork.FldObj) == TRUE){
			//ポケ消失アニメ
			FE_MB_IO_Add( fsys->PairPokeWork.FldObj, MB_FLASH );
			//連れ歩きをバニッシュ
			PairPoke_SetBallInState(fsys);
			(*seq)++;
		}
		break;
	case 6:
		sys_FreeMemoryEz(wait);
		//イベント終了
		return TRUE;
	}
	return FALSE ;
}

//--------------------------------------------------------------
/**
 * 波乗り開始時の連れ歩きの動作
 *
 * @param	player		自機フィールドOBJ
 * @param	pair		連れ歩きフィールドOBJ
 *
 * @retval	none
 */
//--------------------------------------------------------------
static void MoveToPlayer(FIELD_OBJ_PTR player, FIELD_OBJ_PTR pair)
{
	int play_x,play_z;
	int pair_x,pair_z;
	int dif_x,dif_z;
	u8 dir;

	play_x = FieldOBJ_NowPosGX_Get( player );
	play_z = FieldOBJ_NowPosGZ_Get( player );
	pair_x = FieldOBJ_NowPosGX_Get( pair );
	pair_z = FieldOBJ_NowPosGZ_Get( pair );

	dif_x = play_x - pair_x;
	dif_z = play_z - pair_z;
	dir = FieldOBJ_DirDispGet(player);

	if (dif_x < 0){
		//連れ歩き左に移動
		FieldOBJ_AcmdSet( pair, AC_WALK_L_16F );
	}else if(dif_x > 0){
		//連れ歩き右に移動
		FieldOBJ_AcmdSet( pair, AC_WALK_R_16F );
	}else if(dif_z < 0){
		//連れ歩き上に移動
		FieldOBJ_AcmdSet( pair, AC_WALK_U_16F );
	}else if(dif_z > 0){
		//連れ歩き下に移動
		FieldOBJ_AcmdSet( pair, AC_WALK_D_16F );
	}

}

//--------------------------------------------------------------
/**
 * テクスチャID検索
 * @param	inObjCode				検索OBJCODE
 * @retval	int					アーカイブインデックス
 */
//--------------------------------------------------------------
static int GetTexArcID(const int inObjCode)
{
#if 0	//FLDOBJ_COMP
	const FIELD_OBJ_RESMNARC *tbl = DATA_FieldOBJ_ResmNArcTbl_Tex;
	do{
		if( tbl->id == inObjCode ){
			return tbl->narc_id;
		}
		tbl++;
	}while( tbl->id != OBJCODEMAX );
#else
	int ret = FieldOBJ_TextureResIDGetFromCode( inObjCode );
	if(ret >= 0){
		return ret;
	}
#endif
	GF_ASSERT(0);
	return 0;
}

//--------------------------------------------------------------
/**
 * 連れ歩き向きセット
 * @param	fsys			フィールドシステムポインタ
 * @param	inDir			方向
 *
 * @retval	none
 */
//--------------------------------------------------------------
void PairPoke_SetDir(FIELDSYS_WORK *fsys, const u8 inDir)
{
	if (!PairPoke_IsPairPoke(fsys)){
		return;
	}
	FieldOBJ_DirDispCheckSet( fsys->PairPokeWork.FldObj,
							  inDir );
}

//--------------------------------------------------------------
/**
 * 連れ歩きポケモンのパレットを白フラッシュさせるイベントを作成
 *
 * @param	fsys	フィールドシステムポインタ
 * @param	inDiv	色変更分割	1〜16	16で一瞬でカラー変更
 * @param	inWait	変更間隔	カラー変更が一回かかった後の次までのウェイト
 *
 * @retval	BOOL		TRUE:イベント作成	FALSE:イベント未作成
 */
//--------------------------------------------------------------
BOOL PairPokeEvAnm_WhiteFlash(FIELDSYS_WORK * fsys, const u8 inDiv, const u8 inWait)
{
	PPOKE_PAL_FADE_WORK *work;

	//ポケモン連れ歩いていない
	if (!PairPoke_IsPairPoke(fsys)){	//連れ歩いていないなら演出カット
		return FALSE;
	}
	//ポケモン消えてないか？
	if (PairPoke_IsVanish(fsys)){	//消えてたら、演出カット
		return FALSE;
	}

	if (inDiv <= 0){
		return FALSE;
	}

	//メモリ確保
	{
		int size;
		size = sizeof(PPOKE_PAL_FADE_WORK);
		work = sys_AllocMemoryLo(HEAPID_WORLD, size);
		MI_CpuClear8(work, size);
	}
	//設定
	work->DivVal = inDiv;
	work->Wait = inWait;

	//イベントコール
	FieldEvent_Call(fsys->event, WhiteFlash, work);
	return TRUE;
}

//--------------------------------------------------------------
/**
 * パレット白フラッシュイベント
 *
 * @param	event	イベントポインタ
 *
 * @retval	BOOL		TRUE:イベント終了	FALSE:イベント継続
 */
//--------------------------------------------------------------
static BOOL WhiteFlash(GMEVENT_CONTROL * event)
{
	FIELDSYS_WORK * fsys = FieldEvent_GetFieldSysWork(event);
	PPOKE_PAL_FADE_WORK * work = FieldEvent_GetSpecialWork(event);
	int *seq = FieldEvent_GetSeqWork(event);
	switch(*seq){
	case 0:
		//元パレット保存
		{
			FIELD_OBJ_PTR  ptr = PairPoke_GetFldObjPtr(fsys);
			//パレット保存
			{
				int tex_id;
				u8 *start;
				ARCHANDLE *handle;
				void *arc_data;
				NNSG3dResTex *tex;

				tex_id = GetTexArcID( FieldOBJ_OBJCodeGet( ptr ) );	//テクスチャアーカイブIDを取得
				handle = FieldOBJSys_ArcHandleGet( fsys->fldobjsys );
				arc_data = ArchiveDataLoadAllocByHandle( handle, tex_id, HEAPID_WORLD ); //アーカイブからロード
				tex = NNS_G3dGetTex((NNSG3dResFileHeader*) arc_data );
				//パレットロウデータ取得
				start = (u8*)tex + tex->plttInfo.ofsPlttData;
				//パレットコピー
				MI_CpuCopy16( start, work->PalSrc, 16*2*2 );	//16色パレット2本分

				sys_FreeMemoryEz(arc_data);
			}
		}
		(*seq)++;
		break;
	case 1:
		if (work->NowWait != 0){
			work->NowWait--;
			break;
		}
		//目的の変更ができたか？
		work->now_evy+=work->DivVal;
		if (work->now_evy >= 16){
			work->now_evy = 16;
			(*seq)++;
		}
		//カラーチェンジ
		SoftFade(work->PalSrc, work->PalDst, 32, work->now_evy, 0xffff);
		//パレットセット
		{
			BLACT_WORK_PTR	act;
			//連れ歩きポケモンアクター取得
			act = FldOBJ_GetPairPokeAct(fsys->fldobjsys);
			AddVramTransferManager(
				NNS_GFD_DST_3D_TEX_PLTT,		//転送セット
				NNS_GfdGetPlttKeyAddr( BLACT_GetPlttKey( act ) ),
				work->PalDst,
				NNS_GfdGetPlttKeySize(BLACT_GetPlttKey( act )));
		}
		work->NowWait = work->Wait;
		break;
	case 2:
		if (work->NowWait != 0){
			work->NowWait--;
			break;
		}
		//目的の変更ができたか？
		work->now_evy-=work->DivVal;
		if (work->now_evy <= 0){
			(*seq)++;
		}
		//カラーチェンジ
		SoftFade(work->PalSrc, work->PalDst, 32, work->now_evy, 0xffff);
		//パレットセット
		{
			BLACT_WORK_PTR	act;
			//連れ歩きポケモンアクター取得
			act = FldOBJ_GetPairPokeAct(fsys->fldobjsys);
			AddVramTransferManager(
				NNS_GFD_DST_3D_TEX_PLTT,		//転送セット
				NNS_GfdGetPlttKeyAddr( BLACT_GetPlttKey( act ) ),
				work->PalDst,
				NNS_GfdGetPlttKeySize(BLACT_GetPlttKey( act )));
		}
		work->NowWait = work->Wait;
		break;
	case 3:
		//終了
		sys_FreeMemoryEz(work);
		return TRUE;
	}
	return FALSE;
}

//--------------------------------------------------------------
/**
 * 連れ歩きポケモンが自機の隣にいるかを判定する
 *
 * @param	fsys	フィールドシステムポインタ
 *
 * @retval	BOOL		TRUE:隣にいる	FALSE:隣にいない
 */
//--------------------------------------------------------------
BOOL PairPoke_IsNeighbor(FIELDSYS_WORK * fsys)
{
	int player_x,player_z;
	int pair_x,pair_z;
	FIELD_OBJ_PTR player;
	FIELD_OBJ_PTR pair;
	if (!PairPoke_IsVisible(fsys)){
		return FALSE;
	}
	player = Player_FieldOBJGet( fsys->player );
	pair = fsys->PairPokeWork.FldObj;

	//自機と連れ歩きポケ座標を取得
	player_x = FieldOBJ_NowPosGX_Get( player );
	player_z = FieldOBJ_NowPosGZ_Get( player );
	pair_x = FieldOBJ_NowPosGX_Get( pair );
	pair_z = FieldOBJ_NowPosGZ_Get( pair );
	if ( player_x == pair_x ){
		if ( (player_z+1 == pair_z) || (player_z-1) == pair_z ){
			return TRUE;
		}
	}else if( player_z == pair_z ){
		if ( (player_x+1 == pair_x) || (player_x-1) == pair_x ){
			return TRUE;
		}
	}

	return FALSE;
}

//--------------------------------------------------------------
/**
 * 連れ歩きポケモンのポケモンリストナンバーを返す
 *
 * @param	fsys	フィールドシステムポインタ
 *
 * @retval	BOOL		TRUE:隣にいる	FALSE:隣にいない
 */
//--------------------------------------------------------------
u8 PairPoke_GetPokeListNo(FIELDSYS_WORK * fsys)
{
	u8 idx;
	POKEPARTY *my_party = SaveData_GetTemotiPokemon(fsys->savedata);
	idx = EvPoke_GetLivingPokeIdxTop(my_party);
	return idx;
}